package errors

import (
	"fmt"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
)

// 错误码定义
var (
	// 通用错误码 1000-1999
	CodeInternalError   = gcode.New(1001, "系统内部错误", "")
	CodeInvalidParam    = gcode.New(1002, "参数错误", "")
	CodeNotFound        = gcode.New(1003, "资源不存在", "")
	CodeAlreadyExists   = gcode.New(1004, "资源已存在", "")
	CodeUnauthorized    = gcode.New(1005, "未授权", "")
	CodeForbidden       = gcode.New(1006, "禁止访问", "")
	CodeTooManyRequests = gcode.New(1007, "请求过于频繁", "")

	// 数据库错误码 2000-2999
	CodeDatabaseError       = gcode.New(2001, "数据库错误", "")
	CodeDatabaseConnError   = gcode.New(2002, "数据库连接错误", "")
	CodeDatabaseQueryError  = gcode.New(2003, "数据库查询错误", "")
	CodeDatabaseInsertError = gcode.New(2004, "数据库插入错误", "")
	CodeDatabaseUpdateError = gcode.New(2005, "数据库更新错误", "")
	CodeDatabaseDeleteError = gcode.New(2006, "数据库删除错误", "")

	// 股票相关错误码 3000-3999
	CodeStockNotFound      = gcode.New(3001, "股票不存在", "")
	CodeStockAlreadyExists = gcode.New(3002, "股票已存在", "")
	CodeInvalidStockCode   = gcode.New(3003, "无效的股票代码", "")
	CodeInvalidMarket      = gcode.New(3004, "无效的市场代码", "")

	// 股票池相关错误码 4000-4999
	CodePoolNotFound        = gcode.New(4001, "股票池不存在", "")
	CodePoolAlreadyExists   = gcode.New(4002, "股票池已存在", "")
	CodePoolFull            = gcode.New(4003, "股票池已满", "")
	CodeStockNotInPool      = gcode.New(4004, "股票不在股票池中", "")
	CodeStockAlreadyInPool  = gcode.New(4005, "股票已在股票池中", "")
	CodeInvalidPoolType     = gcode.New(4006, "无效的股票池类型", "")
	CodePoolRuleError       = gcode.New(4007, "股票池规则错误", "")

	// 标签相关错误码 5000-5999
	CodeTagNotFound       = gcode.New(5001, "标签不存在", "")
	CodeTagAlreadyExists  = gcode.New(5002, "标签已存在", "")
	CodeInvalidTagCategory = gcode.New(5003, "无效的标签分类", "")
	CodeTagHasChildren    = gcode.New(5004, "标签存在子标签，无法删除", "")
	CodeCircularReference = gcode.New(5005, "标签存在循环引用", "")

	// 策略相关错误码 6000-6999
	CodeStrategyNotFound     = gcode.New(6001, "策略不存在", "")
	CodeStrategyRunning      = gcode.New(6002, "策略正在运行", "")
	CodeInvalidStrategyParam = gcode.New(6003, "无效的策略参数", "")
	CodeStrategyError        = gcode.New(6004, "策略执行错误", "")

	// 交易相关错误码 7000-7999
	CodeInsufficientFunds = gcode.New(7001, "资金不足", "")
	CodeInvalidOrderType  = gcode.New(7002, "无效的订单类型", "")
	CodeMarketClosed      = gcode.New(7003, "市场已关闭", "")
	CodeTradingError      = gcode.New(7004, "交易执行错误", "")

	// 风控相关错误码 8000-8999
	CodeRiskLimitExceeded = gcode.New(8001, "超出风险限制", "")
	CodePositionLimit     = gcode.New(8002, "超出仓位限制", "")
	CodeStopLoss          = gcode.New(8003, "触发止损", "")

	// 数据源相关错误码 9000-9999
	CodeDataSourceError    = gcode.New(9001, "数据源错误", "")
	CodeDataNotAvailable   = gcode.New(9002, "数据不可用", "")
	CodeDataFormatError    = gcode.New(9003, "数据格式错误", "")
	CodeDataSourceTimeout = gcode.New(9004, "数据源超时", "")
)

// BizError 业务错误
type BizError struct {
	Code    gcode.Code
	Message string
	Data    interface{}
}

// Error 实现error接口
func (e *BizError) Error() string {
	return fmt.Sprintf("Code: %v, Message: %s", e.Code.Code(), e.Message)
}

// NewBizError 创建业务错误
func NewBizError(code gcode.Code, message string, data ...interface{}) *BizError {
	var errorData interface{}
	if len(data) > 0 {
		errorData = data[0]
	}
	return &BizError{
		Code:    code,
		Message: message,
		Data:    errorData,
	}
}

// 快捷错误创建函数

// NewInternalError 内部错误
func NewInternalError(message string, data ...interface{}) error {
	if message == "" {
		message = "系统内部错误"
	}
	return NewBizError(CodeInternalError, message, data...)
}

// NewInvalidParam 参数错误
func NewInvalidParam(message string, data ...interface{}) error {
	if message == "" {
		message = "参数错误"
	}
	return NewBizError(CodeInvalidParam, message, data...)
}

// NewNotFound 资源不存在错误
func NewNotFound(resource string, data ...interface{}) error {
	message := fmt.Sprintf("%s不存在", resource)
	return NewBizError(CodeNotFound, message, data...)
}

// NewAlreadyExists 资源已存在错误
func NewAlreadyExists(resource string, data ...interface{}) error {
	message := fmt.Sprintf("%s已存在", resource)
	return NewBizError(CodeAlreadyExists, message, data...)
}

// NewDatabaseError 数据库错误
func NewDatabaseError(operation string, err error, data ...interface{}) error {
	message := fmt.Sprintf("数据库%s失败: %v", operation, err)
	return NewBizError(CodeDatabaseError, message, data...)
}

// NewStockNotFound 股票不存在错误
func NewStockNotFound(code string, data ...interface{}) error {
	message := fmt.Sprintf("股票 %s 不存在", code)
	return NewBizError(CodeStockNotFound, message, data...)
}

// NewStockAlreadyExists 股票已存在错误
func NewStockAlreadyExists(code string, data ...interface{}) error {
	message := fmt.Sprintf("股票 %s 已存在", code)
	return NewBizError(CodeStockAlreadyExists, message, data...)
}

// NewPoolNotFound 股票池不存在错误
func NewPoolNotFound(name string, data ...interface{}) error {
	message := fmt.Sprintf("股票池 %s 不存在", name)
	return NewBizError(CodePoolNotFound, message, data...)
}

// NewPoolFull 股票池已满错误
func NewPoolFull(name string, maxSize int, data ...interface{}) error {
	message := fmt.Sprintf("股票池 %s 已满，最大容量 %d", name, maxSize)
	return NewBizError(CodePoolFull, message, data...)
}

// NewTagNotFound 标签不存在错误
func NewTagNotFound(name string, data ...interface{}) error {
	message := fmt.Sprintf("标签 %s 不存在", name)
	return NewBizError(CodeTagNotFound, message, data...)
}

// WrapError 包装错误，保留原始错误信息
func WrapError(err error, message string) error {
	if err == nil {
		return nil
	}
	
	// 如果已经是BizError，则保留错误码
	if bizErr, ok := err.(*BizError); ok {
		return &BizError{
			Code:    bizErr.Code,
			Message: fmt.Sprintf("%s: %s", message, bizErr.Message),
			Data:    bizErr.Data,
		}
	}
	
	// 否则创建内部错误
	return NewInternalError(fmt.Sprintf("%s: %v", message, err))
}

// IsErrorCode 检查错误是否为指定错误码
func IsErrorCode(err error, code gcode.Code) bool {
	if bizErr, ok := err.(*BizError); ok {
		return bizErr.Code.Code() == code.Code()
	}
	return false
}

// GetErrorCode 获取错误码
func GetErrorCode(err error) gcode.Code {
	if bizErr, ok := err.(*BizError); ok {
		return bizErr.Code
	}
	return CodeInternalError
}

// GetErrorMessage 获取错误消息
func GetErrorMessage(err error) string {
	if bizErr, ok := err.(*BizError); ok {
		return bizErr.Message
	}
	return err.Error()
}

// GetErrorData 获取错误数据
func GetErrorData(err error) interface{} {
	if bizErr, ok := err.(*BizError); ok {
		return bizErr.Data
	}
	return nil
}